interface DentifyProps {
  fontSizeMin?: number;
  fontSizeMax?: number;
  canvasWidth?: number;
  canvasHeight?: number;
  onUpdateForm?: (code: string) => void;
}
import { useEffect, useRef, useImperativeHandle, forwardRef } from "react";
export interface DentifyHandle {
  drawPic: () => void;
}
const Dentify = forwardRef<DentifyHandle, DentifyProps>((props, ref) => {
  const {
    fontSizeMin = 30,
    fontSizeMax = 30,
    canvasWidth = 100,
    canvasHeight = 50,
    onUpdateForm,
  } = props;
  const identifyCodes =
    "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  const identifyCode = useRef("");
  // 生成一个随机数
  const randomNum = (min: number, max: number) => {
    return Math.floor(Math.random() * (max - min) + min);
  };
  // 生成一个随机的颜色
  const randomColor = (min: number, max: number) => {
    const r = randomNum(min, max);
    const g = randomNum(min, max);
    const b = randomNum(min, max);
    return "rgb(" + r + "," + g + "," + b + ")";
  };
  // 暴露给父组件的方法
  useImperativeHandle(ref, () => ({
    // 可以暴露更多方法
    drawPic: () => {
      drawPic();
    },
  }));
  //画图
  const drawPic = () => {
    makeCode(4);
    const canvas = document.getElementById("s-canvas") as HTMLCanvasElement;
    //创建一个2D对象作为上下文。
    const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
    ctx.textBaseline = "bottom";
    // 绘制背景
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);
    // 绘制文字
    for (let i = 0; i < identifyCode.current.length; i++) {
      drawText(ctx, identifyCode.current[i], i);
    }
    drawLine(ctx);
    drawDot(ctx);
  };
  //在画布上显示数据
  const drawText = (
    ctx: CanvasRenderingContext2D,
    txt: string,
    i: number
  ): void => {
    ctx.fillStyle = randomColor(50, 160); // 随机生成字体颜色
    ctx.font = randomNum(fontSizeMin, fontSizeMax) + "px SimHei"; // 随机生成字体大小
    const x = (i + 1) * (canvasWidth / (identifyCode.current.length + 1));
    const y = randomNum(fontSizeMax, canvasHeight - 5);
    const deg = randomNum(-30, 30);
    // 修改坐标原点和旋转角度
    ctx.translate(x, y);
    ctx.rotate((deg * Math.PI) / 180);
    ctx.fillText(txt, 0, 0);
    // 恢复坐标原点和旋转角度
    ctx.rotate((-deg * Math.PI) / 180);
    ctx.translate(-x, -y);
  };
  // 绘制干扰线
  const drawLine = (ctx: CanvasRenderingContext2D): void => {
    for (let i = 0; i < 4; i++) {
      ctx.strokeStyle = randomColor(100, 200);
      ctx.beginPath();
      ctx.moveTo(randomNum(0, canvasWidth), randomNum(0, canvasHeight));
      ctx.lineTo(randomNum(0, canvasWidth), randomNum(0, canvasHeight));
      ctx.stroke();
    }
  };
  // 绘制干扰点
  const drawDot = (ctx: CanvasRenderingContext2D): void => {
    for (let i = 0; i < 30; i++) {
      ctx.fillStyle = randomColor(0, 255);
      ctx.beginPath();
      ctx.arc(
        randomNum(0, canvasWidth),
        randomNum(0, canvasHeight),
        1,
        0,
        2 * Math.PI
      );
      ctx.fill();
    }
  };
  //获取验证码的值
  const makeCode = (l: number) => {
    identifyCode.current = "";
    for (let i = 0; i < l; i++) {
      //通过循环获取字符串内随机几位
      identifyCode.current += identifyCodes[randomNum(0, identifyCodes.length)];
    }
    onUpdateForm?.(identifyCode.current);
  };
  useEffect(() => {
    drawPic();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [identifyCode]);
  return (
    <>
      <canvas
        id="s-canvas"
        width={canvasWidth}
        height={canvasHeight}
        onClick={drawPic}
      ></canvas>
    </>
  );
});
export default Dentify;
